/*
 * UserTask.c
 *
 *      Author: Honrun
 */
#include "gd32w51x.h"
#include "systick.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "main.h"
#include "version.h"

#include "rtthread.h"
#include "cpuusage.h"

#include "DevicesDelay.h"
#include "DevicesTime.h"
#include "DevicesKey.h"
#include "DevicesLed.h"
#include "DevicesUart.h"
#include "DevicesQueue.h"
#include "DevicesEEPROM.h"
#include "DevicesADC.h"
#include "DevicesFlash.h"
#include "DevicesIFRP.h"
#include "DevicesM3-S.h"
#include "DevicesPower.h"
#include "DevicesSoftTimer.h"

#include "lcd_driver.h"
#include "NesSystem.h"
#include "UserJson.h"
#include "UserTask.h"


rt_thread_t g_TaskInitHand = RT_NULL;           /* 系统初始化任务句柄 */
rt_thread_t g_TaskReadMessageHand = RT_NULL;    /* 读取消息任务句柄 */
rt_thread_t g_TaskKeyHand = RT_NULL;            /* 按键 */
rt_thread_t g_TaskCPUUsageGetHand = RT_NULL;    /* CPU利用率 */
rt_thread_t g_TaskSimulatorNESHand = RT_NULL;   /* NES模拟器 */

rt_sem_t g_SemKey = RT_NULL;                    /* 按键中断同步信号量 */
rt_sem_t g_SemReadMessage = RT_NULL;            /* 读取消息中断同步信号量 */



void scheduler_hook(struct rt_thread* from, struct rt_thread* to)
{
    // printf("\n\r[ Task from: %s\t\tto: %s ]\r\n", from->name, to->name);
}


static SoftTimerTypeDef st_softTimerINPUT_A = {0};
static SoftTimerTypeDef st_softTimerINPUT_B = {0};
static SoftTimerTypeDef st_softTimerINPUT_Select = {0};
static SoftTimerTypeDef st_softTimerINPUT_Start = {0};
static SoftTimerTypeDef st_softTimerINPUT_Up = {0};
static SoftTimerTypeDef st_softTimerINPUT_Down = {0};
static SoftTimerTypeDef st_softTimerINPUT_Left = {0};
static SoftTimerTypeDef st_softTimerINPUT_Right = {0};

void vRFKeyScanf(void)
{
    if(enumSoftTimerGetState(&st_softTimerINPUT_A) == softTimerOpen)
        vNesInputBitSet(NES_JOYPADALL, NesInput_A);
    else
        vNesInputBitReset(NES_JOYPADALL, NesInput_A);

    if(enumSoftTimerGetState(&st_softTimerINPUT_B) == softTimerOpen)
        vNesInputBitSet(NES_JOYPADALL, NesInput_B);
    else
        vNesInputBitReset(NES_JOYPADALL, NesInput_B);

    if(enumSoftTimerGetState(&st_softTimerINPUT_Select) == softTimerOpen)
        vNesInputBitSet(NES_JOYPADALL, NesInput_Select);
    else
        vNesInputBitReset(NES_JOYPADALL, NesInput_Select);

    if(enumSoftTimerGetState(&st_softTimerINPUT_Start) == softTimerOpen)
        vNesInputBitSet(NES_JOYPADALL, NesInput_Start);
    else
        vNesInputBitReset(NES_JOYPADALL, NesInput_Start);

    if(enumSoftTimerGetState(&st_softTimerINPUT_Up) == softTimerOpen)
        vNesInputBitSet(NES_JOYPADALL, NesInput_Up);
    else
        vNesInputBitReset(NES_JOYPADALL, NesInput_Up);

    if(enumSoftTimerGetState(&st_softTimerINPUT_Down) == softTimerOpen)
        vNesInputBitSet(NES_JOYPADALL, NesInput_Down);
    else
        vNesInputBitReset(NES_JOYPADALL, NesInput_Down);

    if(enumSoftTimerGetState(&st_softTimerINPUT_Left) == softTimerOpen)
        vNesInputBitSet(NES_JOYPADALL, NesInput_Left);
    else
        vNesInputBitReset(NES_JOYPADALL, NesInput_Left);

    if(enumSoftTimerGetState(&st_softTimerINPUT_Right) == softTimerOpen)
        vNesInputBitSet(NES_JOYPADALL, NesInput_Right);
    else
        vNesInputBitReset(NES_JOYPADALL, NesInput_Right);
}


void vTaskReadMessage(void *pvParameters)
{
    static uint8_t st_TaskReadMessageBuff[QUEUE_MAX_LENGTH + 4] = {0};
    M3STypeDef typeM3SData = {0};
    int32_t iLength = 0;
    uint8_t ucByte = 0;

    printf("vTaskReadMessage start.\r\n");

    while (1)
    {
        /* 等待消息 */
        rt_sem_take(g_SemReadMessage, RT_WAITING_FOREVER);

        /* 串口0接收到的数据 */
        while((iLength = iQueueGetLengthOfOccupy(&g_TypeQueueUart0Read)) != 0)
        {
            iLength = iLength < QUEUE_MAX_LENGTH ? iLength : QUEUE_MAX_LENGTH;

            enumQueuePopDatas(&g_TypeQueueUart0Read, st_TaskReadMessageBuff, iLength);

            st_TaskReadMessageBuff[iLength] = 0;
            printf("%s: %s\r\n", g_TypeQueueUart0Read.pcName, st_TaskReadMessageBuff);
        }

        /* 串口1接收到的数据 */
        while(enumQueuePopByte(&g_TypeQueueUart1Read, &ucByte) == queueNormal)
        {
            /* 解析数据 */
            if(enumM3SDecode(&typeM3SData, ucByte) == M3SSucceed)
                cM3SSetInfo(&typeM3SData);
        }

        /* 串口2接收到的数据 */
        while((iLength = iQueueGetLengthOfSeparetor(&g_TypeQueueUart2Read, FRAME_SEPARETOR)) != 0)
        {
            iLength = iLength < QUEUE_MAX_LENGTH ? iLength : QUEUE_MAX_LENGTH;

            enumQueuePopDatas(&g_TypeQueueUart2Read, st_TaskReadMessageBuff, iLength);

            st_TaskReadMessageBuff[iLength] = 0;
            printf("%s: %s\r\n", g_TypeQueueUart2Read.pcName, st_TaskReadMessageBuff);

            /* 进行json解析 */
            cJsonParser((char *)st_TaskReadMessageBuff);
        }
    }
}

void vTaskKey(void *pvParameters)
{
    static IFRPCodeType ptypeIFRPData = {0};
    static KeyTypeDef typeKeyData = {0};
    int16_t sTime = 0;
    int8_t cNECState = 0;

    printf("vTaskKey start.\r\n");


    cSoftTimerSetMs(&st_softTimerINPUT_A, 120, softTimerClose);
    cSoftTimerSetMs(&st_softTimerINPUT_B, 120, softTimerClose);
    cSoftTimerSetMs(&st_softTimerINPUT_Select, 120, softTimerClose);
    cSoftTimerSetMs(&st_softTimerINPUT_Start, 120, softTimerClose);
    cSoftTimerSetMs(&st_softTimerINPUT_Up, 120, softTimerClose);
    cSoftTimerSetMs(&st_softTimerINPUT_Down, 120, softTimerClose);
    cSoftTimerSetMs(&st_softTimerINPUT_Left, 120, softTimerClose);
    cSoftTimerSetMs(&st_softTimerINPUT_Right, 120, softTimerClose);

    while (1)
    {
        /* 等待消息 */
        // rt_sem_take(g_SemKey, RT_WAITING_FOREVER);
        rt_sem_take(g_SemKey, 20);

        /* 按键输入 */
        while(enumQueuePopDatas(&g_TypeQueueKeyInput, (uint8_t *)&typeKeyData, sizeof(KeyTypeDef)) == queueNormal)
        {
            /* 机械按键 */
            if(typeKeyData.valuePress & KEY_RESET)
            {
                if(typeKeyData.state == (keyShort | keyCut))
                    cSoftTimerReset(&st_softTimerINPUT_Select);
                else if(typeKeyData.state == keyLong)
                    cSoftTimerReset(&st_softTimerINPUT_Start);
            }

            /* 触摸按键1 */
            if(typeKeyData.valuePress & KEY_TOUCH1)
            {
                if((typeKeyData.state == keyShort) || (typeKeyData.state == keyContinuous))
                    cSoftTimerReset(&st_softTimerINPUT_A);
            }

            /* 触摸按键2 */
            if(typeKeyData.valuePress & KEY_TOUCH2)
            {
                if((typeKeyData.state == keyShort) || (typeKeyData.state == keyContinuous))
                    cSoftTimerReset(&st_softTimerINPUT_B);
            }
        }

        /* 红外接收器接收到的数据 */
        while(enumQueuePopDatas(&g_TypeQueueIFRPDecode, &sTime, 2) == queueNormal)
        {
            cNECState = cIFRPDecode(&ptypeIFRPData, sTime);
            /* 解析数据 */
            if((cNECState == necSucceed) || (cNECState == necRepeat))
            {
                switch(ptypeIFRPData.data)
                {
                    case 0x00FF44BB: cSoftTimerReset(&st_softTimerINPUT_Up); break;
                    case 0x00FFA857: cSoftTimerReset(&st_softTimerINPUT_Down); break;
                    case 0x00FFD827: cSoftTimerReset(&st_softTimerINPUT_Left); break;
                    case 0x00FFC43B: cSoftTimerReset(&st_softTimerINPUT_Right); break;
                    case 0x00FF7887: cSoftTimerReset(&st_softTimerINPUT_A); break;
                    case 0x00FF24DB: cSoftTimerReset(&st_softTimerINPUT_B); break;
                    case 0xE580: cSoftTimerReset(&st_softTimerINPUT_Select); break;

                    case 0x41DC:
                    case 0x8823:
                    case 0x5AA501A7: cSoftTimerReset(&st_softTimerINPUT_Start); break;

                    default: break;
                }
            }
        }

        vRFKeyScanf();
    }
}

uint8_t major = 0, minor = 0, majorOld = 0;

void vTaskCPUUsageGet(void *pvParameters)
{

    printf("vTaskCPUUsageGet start.\r\n");

    while (1)
    {
        cpu_usage_get(&major, &minor);

        if(majorOld != major)
        {
            majorOld = major;
            printf("\n\rCPU usage: %d.%d%%\r\n", major, minor);
        }

        rt_thread_mdelay(1000);
    }
}

void vTaskSimulatorNES(void *pvParameters)
{
    int32_t iTimeUsDeltal = 0;

    printf("vTaskSimulatorNES start.\r\n");

    vNesInit();


    while (1)
    {
        gpio_bit_reset(GPIOC, GPIO_PIN_3);

        vNesExec();

        gpio_bit_set(GPIOC, GPIO_PIN_3);
    }
}

void vTaskInit(void *pvParameters)
{
    printf("\n\rRT-Thread start succeed...\r\n");

    /* 新建信号量 */
    g_SemKey = rt_sem_create("key sem", 0, RT_IPC_FLAG_FIFO);

    g_SemReadMessage = rt_sem_create("read message sem", 0, RT_IPC_FLAG_FIFO);


    /* 新建任务 */
    g_TaskReadMessageHand =  rt_thread_create("Read Message",  vTaskReadMessage,  RT_NULL, 1024, 5, 20);
    rt_thread_startup(g_TaskReadMessageHand);

    g_TaskSimulatorNESHand = rt_thread_create("Simulator NES", vTaskSimulatorNES, RT_NULL, 1024, 6, 20);
    rt_thread_startup(g_TaskSimulatorNESHand);

    g_TaskKeyHand =          rt_thread_create("Key",           vTaskKey,          RT_NULL, 1024, 7, 20);
    rt_thread_startup(g_TaskKeyHand);

    g_TaskCPUUsageGetHand =  rt_thread_create("CPU usage",     vTaskCPUUsageGet,  RT_NULL, 1024, 8, 20);
    rt_thread_startup(g_TaskCPUUsageGetHand);


    rt_scheduler_sethook(scheduler_hook);


    printf("SystemInit start.\r\n");
    vUserSystemInit();
    printf("\n\rSystemInit succeed.\r\n\n");

    lcd_refresh();

    /* 删除自己 */
    rt_thread_delete(g_TaskInitHand);
}
